package android.magical;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

public class CalendarFragment extends Fragment {

	private final String TAG = "CalendarFragment";
	private final int[] numberDaysOfMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	private static GridAdapter adapter;
	private static GregorianCalendar calendar;
	private int nbDaysPrevMonth, nbDaysCurrentMonth, nbDaysNextMonth;

	public static CalendarFragment newInstance(int i) {
		CalendarFragment f = new CalendarFragment();       
		// Supply num input as an argument.
		Bundle args = new Bundle();
		args.putInt("num", i);
		f.setArguments(args);
		return f;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.v(TAG, "Created.");
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		Log.v(TAG, "View Created.");
		// Inflate the layout for this fragment
		View v = inflater.inflate(R.layout.calendar, container, false);

		// Retrieve the number of the fragment in the pageViewer to determine which month
		// this method is creating
		int num = this.getArguments().getInt("num");
		calendar = new GregorianCalendar();
		calendar.add(Calendar.MONTH, num-(MainActivity.NUM_ITEMS/2));

		GridView mGridView = (GridView) v.findViewById(R.id.gridview);
		List<CalendarItem> daysOfMonth = new ArrayList<CalendarItem>();
		fillDaysOfMonth(daysOfMonth);
		adapter = new GridAdapter(getActivity(), daysOfMonth, num);
		mGridView.setAdapter(adapter);

		mGridView.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> parent, View v, int position, long id){
				CalendarItem day = ((ViewHolder)v.getTag()).dayOfMonth;
				GregorianCalendar cal = ((MainActivity)getActivity()).getmCalendar();
				int year = cal.get(GregorianCalendar.YEAR);
				int month = cal.get(GregorianCalendar.MONTH);
				if (day.whichMonth==0){
					EventsFragment events = ((MainActivity)getActivity()).getEventsFragment();
					Log.v(TAG, "Trying to get events for: " + day.idDay + "/" + (month+1) + "/" + year);
					((MainActivity)getActivity()).setChosenDate(day.idDay, month, year);
					events.showEvents(day.idDay, month, year);
					MainActivity.lastChosenDay.setBackgroundResource(R.drawable.day_borders);
					v.setBackgroundResource(R.drawable.day_borders_after_click);
					MainActivity.lastChosenDay = v;

				}
				else if(day.whichMonth==-1){
					ViewPager pager = ((MainActivity)getActivity()).getPager();
					pager.setCurrentItem(pager.getCurrentItem()-1, false);
					MainActivity.lastChosenDay.setBackgroundResource(R.drawable.day_borders);
					int dayId = ((MainActivity)getActivity()).getPrevMonthSize() - nbDaysPrevMonth + position;
					Log.v(TAG, "dayId " + dayId);
					((MainActivity)getActivity()).setChosenDate(dayId+1, month-1, year);
					View prev = ((MainActivity)getActivity()).getPrevMonthDay(dayId);
					prev.setBackgroundResource(R.drawable.day_borders_after_click);
					MainActivity.lastChosenDay = prev;
					((MainActivity)getActivity()).clearPrevMonthDays();
				}
				else if(day.whichMonth==1){
					ViewPager pager = ((MainActivity)getActivity()).getPager();
					pager.setCurrentItem(pager.getCurrentItem()+1, false);
					MainActivity.lastChosenDay.setBackgroundResource(R.drawable.day_borders);
					int dayId = position - nbDaysCurrentMonth - nbDaysPrevMonth;
					//Log.v(TAG, "dayId " + dayId);
					((MainActivity)getActivity()).setChosenDate(dayId+1, month+1, year);
					View next = ((MainActivity)getActivity()).getNextMonthDay(dayId);
					next.setBackgroundResource(R.drawable.day_borders_after_click);
					MainActivity.lastChosenDay = next;
					((MainActivity)getActivity()).clearNextMonthDays();
				}
			}
		});
		return v;
	}

	/**
	 * Initialises a list daysOfMonth with objects of type CalendarItem. This list contains all the information
	 * necessary to display the days within the gridView. Then the GridViewAdapter will read the information from
	 * this list to create the view of each day in the gridView
	 * 
	 * @param daysOfMonth the list which contains the days' inforamtion
	 */
	public void fillDaysOfMonth(List<CalendarItem> daysOfMonth){
		DatabaseControl dbControl = ((MainActivity)getActivity()).getDatabase();
		int month = calendar.get(Calendar.MONTH);
		int year = calendar.get(GregorianCalendar.YEAR);
		System.out.println(""+month);
		nbDaysCurrentMonth = numberDaysOfMonth[month];
		if (month==1 && calendar.isLeapYear(calendar.get(Calendar.YEAR))){
			nbDaysCurrentMonth = 29;
		}
		// Add the days for the previous month
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		int firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
		if (firstDayOfWeek == Calendar.SUNDAY){
			nbDaysPrevMonth = 6;
		}
		else {
			nbDaysPrevMonth = firstDayOfWeek-2;
		}
		for (int j=0 ; j<nbDaysPrevMonth ; j++) {
			int prevMonth;
			if (month==0){prevMonth = 11;}
			else{prevMonth = month-1;}
			int idLastDay = numberDaysOfMonth[prevMonth];
			if (prevMonth==1 && calendar.isLeapYear(calendar.get(Calendar.YEAR))){
				idLastDay = 29;
			}
			daysOfMonth.add(j, new CalendarItem(idLastDay-nbDaysPrevMonth+j+1, -1, dbControl.hasItem("stringDate", "owner")));
		}

		// Add the days of the current month
		for (int j=0 ; j<nbDaysCurrentMonth ; j++){
			String date = (j+1)+"/"+(month+1)+"/"+year;
			//Log.v(TAG, "adding calendar item: " + date);
			daysOfMonth.add(j+nbDaysPrevMonth, new CalendarItem(j+1, 0, dbControl.hasItem(date, ((MainActivity)getActivity()).getOwnerName())));
		}

		// Add the days from the next month
		calendar.set(Calendar.DAY_OF_MONTH, nbDaysCurrentMonth);
		int lastDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
		if (lastDayOfWeek!=Calendar.SUNDAY){
			nbDaysNextMonth = 8-lastDayOfWeek;
			for (int j=0 ; j<nbDaysNextMonth ; j++) {
				daysOfMonth.add(j+nbDaysPrevMonth+nbDaysCurrentMonth, new CalendarItem(j+1, 1, dbControl.hasItem("stringDate", "owner")));
			}
		}
	}

	// This class is the adapter used to generate the gridView.
	public class GridAdapter extends BaseAdapter {

		private LayoutInflater inflater;
		private List<CalendarItem> daysOfMonth;
		private int num;

		public GridAdapter(Context context, List<CalendarItem> daysOfMonth, int num){
			this.inflater = LayoutInflater.from(context);
			this.daysOfMonth = daysOfMonth;
			this.num = num;
		}

		@Override
		public int getCount() {
			if (this.daysOfMonth==null) {
				return 0;
			}
			else {
				return this.daysOfMonth.size();
			}
		}

		@Override
		public Object getItem(int position) {
			return this.daysOfMonth.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null){
				convertView = this.inflater.inflate(R.layout.griditem, null);
				ViewHolder newViewHoder = new ViewHolder();
				newViewHoder.idDay = (TextView) convertView.findViewById(R.id.id_day);
				newViewHoder.personalEvent = (ImageView) convertView.findViewById(R.id.personal_event);
				newViewHoder.sharedEvent = (ImageView) convertView.findViewById(R.id.shared_event);
				newViewHoder.dayOfMonth = this.daysOfMonth.get(position);
				convertView.setTag(newViewHoder);
			}
			ViewHolder viewHolder = (ViewHolder) convertView.getTag();
			CalendarItem day = this.daysOfMonth.get(position);
			viewHolder.dayOfMonth = day;

			viewHolder.idDay.setText(""+day.idDay);
			if (day.whichMonth==0){
				viewHolder.idDay.setTextColor(0xFFFFFFFF);
				GregorianCalendar temp = new GregorianCalendar();
				MainActivity activity = (MainActivity) getActivity();
				if (this.num==MainActivity.initialPosition && day.idDay==temp.get(Calendar.DAY_OF_MONTH)){
					if(MainActivity.lastChosenDay == null){
						Log.v(TAG, "Selecting current day");
						convertView.setBackgroundResource(R.drawable.day_borders_after_click);
						MainActivity.lastChosenDay = convertView;
						activity.setChosenDate(day.idDay, temp.get(Calendar.MONTH), temp.get(Calendar.YEAR));
					}
				}

				if(this.num > activity.getPager().getCurrentItem()){
					if(activity.isNextMonthFull())	{
						Log.v(TAG, "Next month full - CLEAR");
						activity.clearNextMonthDays();
						activity.setNextMonthFull(false);
					}
					//Log.v(TAG, "adding next month day:" + day.idDay + " into array");
					activity.addNextMonthDay(convertView);
				} 
				else if(this.num < activity.getPager().getCurrentItem()){
					if(activity.isPrevMonthFull())	{
						Log.v(TAG, "Prev month full - CLEAR");
						activity.clearPrevMonthDays();
						activity.setPrevMonthFull(false);
					}
					Log.v(TAG, "adding prev month day:" + day.idDay + " into array");
					activity.addPrevMonthDay(convertView);
				} 
				else if(this.num == activity.getPager().getCurrentItem()){
					if(activity.isThisMonthFull())	{
						Log.v(TAG, "This month full - CLEAR");
						activity.clearThisMonthDays();
						activity.setThisMonthFull(false);
					}
					activity.addThisMonthDay(convertView);
				}

				if (day.hasItem==1){
					viewHolder.personalEvent.setVisibility(View.VISIBLE);
					viewHolder.sharedEvent.setVisibility(View.INVISIBLE);
				}
				else if (day.hasItem==2){
					viewHolder.personalEvent.setVisibility(View.INVISIBLE);
					viewHolder.sharedEvent.setVisibility(View.VISIBLE);
				}
				else if (day.hasItem==3){
					viewHolder.personalEvent.setVisibility(View.VISIBLE);
					viewHolder.sharedEvent.setVisibility(View.VISIBLE);
				}
				else {
					viewHolder.personalEvent.setVisibility(View.INVISIBLE);
					viewHolder.sharedEvent.setVisibility(View.INVISIBLE);
				}
			}
			else {
				viewHolder.idDay.setTextColor(0xFFB4AF91);
				viewHolder.personalEvent.setVisibility(View.INVISIBLE);
				viewHolder.sharedEvent.setVisibility(View.INVISIBLE);
			}
			return convertView;
		}

	}

	// Used to keep references to the graphical elements of the view griditem
	// Thus minimises the calls to findViewById and optimizes the application
	// when the grid is scrollable for very little screen
	static class ViewHolder{
		TextView idDay;
		ImageView personalEvent;
		ImageView sharedEvent;
		CalendarItem dayOfMonth;
	}

	// This class stores information about a day needed to display the gridview of the calendar
	public class CalendarItem{
		private int idDay;
		private int whichMonth;
		private int hasItem;
		public CalendarItem(int idDay, int whichMonth, int hasItem){
			this.whichMonth = whichMonth;
			this.idDay = idDay;
			this.hasItem = hasItem;
		}
	}
}
